#include "fig_pickup.h"
#include "fighter.h"
#include "fig_sfx_manager.h"
#include "fig_player_craft.h"
#include "fig_pickup_manager.h"
#include "fig_sounds.h"
#include "fig_award_tracker.h"
#include "fig_gamecenter.h"
#include "fig_vars.h"
#include "fig_constants.h"
#include "fig_pickup_animation.h"
#include "fig_conversation.h"

#include "dd/dd_man.h"
#include "math/math_core.h"
#include "math/facing.h"
#include "num/rand.h"



FIGPickup::FIGPickup(FIGPickup::PICKUP_TYPES Type,const math::Vec2& P): 
								m_Pos(P),
								m_Type(Type),
								m_Rotation(0.0f),
								m_State(PICKUP_STATE_NONE),
								m_pSFX(NULL),
								m_RotationSpeed(0)
{
	m_CircleCounter.SetLimit(4.0f);
	LoadSprite();	

	m_GlowCounter.SetLimit(2.5f);
	m_GlowCounter.ForceReady();

}
	


std::string		FIGPickup::GetSpriteFile1(PICKUP_TYPES Type)
{
	switch(Type)
	{
		case PICKUP_TYPE_WEAPON_BLUE:
			return "blue_item";
		
		case PICKUP_TYPE_WEAPON_RED:
			return "red_item";
		
		case PICKUP_TYPE_WEAPON_GREEN:
			return "green_item";
		
		case PICKUP_TYPE_HEALTH:
			return "redcross_frame";			
		
		case PICKUP_TYPE_NUKE:
		    return "nuclear_item";
		
		case PICKUP_TYPE_SHIELD:
			return "armor";
		
		case PICKUP_TYPE_STAR:
			return "star_pick_up_item";
		
		case PICKUP_TYPE_ROKET_SHOOT:
			return "missile_pick_up";
		
		case PICKUP_TYPE_1UP:
			return "player_up_item";

		case PICKUP_ORB_RED:
			return "red_ball";

		case PICKUP_ORB_GREEN:
			return "green_ball";

		case PICKUP_ORB_BLUE:
			return "blue_ball";

		case PICKUP_NUKE_BUTTON:
			return "ui_nuclear";
		
	}
	return "";
}

std::string		FIGPickup::GetSpriteFile2(PICKUP_TYPES Type)
{
	switch(Type)
	{ 		
		case PICKUP_TYPE_HEALTH:
			return "red_cross"; 			
		break;		
	}
	return "";
}


void	FIGPickup::LoadSprite()
{
	Load(GetSpriteFile1(m_Type),GetSpriteFile2(m_Type));

	switch(m_Type)
	{
		case PICKUP_TYPE_HEALTH:		
			m_RotationSpeed = 0.1f;
			break;
		case PICKUP_TYPE_ROKET_SHOOT:
			m_RotationSpeed = 0.25f;			
		break;   				
		default:
			m_RotationSpeed = 0;
			break;
	}                   	
}


void	FIGPickup::Load(const std::string& Name,const std::string& Glow)
{
	m_Sprite.Create(Name);
	m_SpriteGlow.Create(Glow);
	m_Radius = m_SpriteGlow.m_SizeOriginal.x * 0.5f;
}

void	FIGPickup::Render(const math::Vec2& Offset, float Scale)
{
	if(!m_IsAlive)
		return;

	m_Sprite.m_Pos = m_Pos + Offset;
	m_Sprite.m_Size = m_Sprite.m_SizeOriginal * Scale;
	m_Sprite.m_Rotation = m_Rotation;
	m_Sprite.RenderRotated();

	if(m_SpriteGlow.GetImage())
	{
		m_SpriteGlow.m_Pos = m_Pos + Offset;
		m_SpriteGlow.m_Size = m_SpriteGlow.m_SizeOriginal * Scale;
		float c = m_GlowCounter.GetProgress();

		if(c < 0.5f)
			c += 0.5f;
		else
		{
			c = 1.0f - c;
			c += 0.5f;
		}
				
		m_SpriteGlow.m_Color = ColorfRGBA(1.0f * c ,1.0f * c,1.0f * c,1.0f);

		m_SpriteGlow.RenderRotated();
	}
}
	
void	FIGPickup::RenderDebug(const math::Vec2& Offset, float Scale)
{
	if(!m_IsAlive)
		return;	
    	
	dd::Manager&	DD = dd::Manager::Instance();
	DD.AddCircle2D( m_Pos+Offset, m_Radius*Scale, ColorRGBA(255,0,0) );	
}
	
void	FIGPickup::Tick(float dt)
{
	if(!m_IsAlive)
		return;
    
    m_Sprite.Tick(dt);
	m_SpriteGlow.Tick(dt);

	if(m_Type == PICKUP_TYPE_STAR && 
		FIGPlayerCraft::Instance().IsAlive()
		)
	{
		math::Vec2 PlayerPos = FIGPlayerCraft::Instance().GetPos();
		math::Vec2 Dir = (PlayerPos - m_Pos);
		float Dist =	Dir.Magnitude();
		math::Vec2 Size = m_Sprite.m_SizeOriginal * Fighter::Instance().GetScale();
		if( Dist < Size.x * 2.5f)
		{
			Dir.Normalize();
			m_Pos += ( Dir * dt * 0.5f );
		}
		else
		{
			Tick_States(dt);
		}

	}
	else
	{
		Tick_States(dt);
	}


	m_Rotation -= (360 * dt * m_RotationSpeed);

	if(m_Rotation < 0.0f)
		m_Rotation = 360.0f;

	HitTest();

	m_GlowCounter.Tick(dt);
	if(m_GlowCounter.IsReady())
		m_GlowCounter.Reset();

	if(m_Pos.y > 1.0 + (m_Sprite.m_SizeOriginal.y * 0.5f))
	{
		m_IsAlive = false;
		if(m_pSFX)
		{
			m_pSFX->ToDie();
			m_pSFX = NULL;
		}
	}

	if(m_pSFX)
		m_pSFX->FollowMe(m_Pos);
	
}

void		FIGPickup::Tick_States(float dt)
{
   switch(m_State)
   {
		case PICKUP_STATE_SPAWN_MOVEMENT:
			Tick_SpawnMovment(dt);
		break;
		case PICKUP_STATE_CIRCLE_AROUND:
			Tick_CircleAround(dt);
		break;
		case PICKUP_EATEN_ANIMATION:
			Tick_Eaten_Animation(dt);
		break;
		
		default:
			break;

   }
}
	
void		FIGPickup::Tick_SpawnMovment(float dt)
{
	m_SpawnMovementTime -= dt;
	if(m_SpawnMovementTime <= 0)
	{
		m_State = PICKUP_STATE_CIRCLE_AROUND;
	}

	math::Vec2 Dir = math::Facing::VectorFromAngle(m_SpawnMovementDegree);
	m_Pos += (Dir * dt * 0.2f );
	if(m_Pos.x > 1.0f)
		m_Pos.x = 1.0f;

	if(m_Pos.x < 0.0f)
		m_Pos.x = 0.0f;

	
}

void		FIGPickup::Tick_CircleAround(float dt)
{
	m_CircleCounter.Tick(dt);
	if(m_CircleCounter.IsReady())
	{
		m_CircleCounter.Reset(); 

		if(m_Type < PICKUP_TYPE_WEAPON_COUNT)
		{
			if(m_Type == PICKUP_TYPE_WEAPON_RED)
			{
				//FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_WEAPON_GREEN,m_Pos);
				m_Type = PICKUP_TYPE_WEAPON_GREEN;
				m_Sprite.Create(GetSpriteFile1(m_Type));
			}
			else if(m_Type == PICKUP_TYPE_WEAPON_GREEN)
			{
				//FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_WEAPON_BLUE,m_Pos);
				m_Type = PICKUP_TYPE_WEAPON_BLUE;
				m_Sprite.Create(GetSpriteFile1(m_Type));
			}
			else if(m_Type == PICKUP_TYPE_WEAPON_BLUE)
			{
				m_Type = PICKUP_TYPE_WEAPON_RED;
				m_Sprite.Create(GetSpriteFile1(m_Type));
				//FIGPickupManager::Instance().Spawn(FIGPickup::PICKUP_TYPE_WEAPON_RED,m_Pos);
			}
			//m_IsAlive = false;
			//if(m_pSFX)
			//{
			//	m_pSFX->ToDie();
			//	m_pSFX = NULL;
			//}
		}
		
		
	}

	const float Radius = 0.1f;
	m_Pos.x += (cosf(m_CircleCounter.GetProgress() * MATH_2PI )  * Radius *  dt ); 
	m_Pos.y += (sinf(m_CircleCounter.GetProgress() * MATH_2PI)  * Radius *  dt );  
	m_Pos.y += (0.03f * dt);
}

void		FIGPickup::Tick_Eaten_Animation(float dt)
{

}
	

void		FIGPickup::ReSpawn()
{
	
	if(m_pSFX)
	{
		// clean previous sfx if any
		m_pSFX->ToDie();
		m_pSFX = NULL;
	}
	if(m_Type == PICKUP_TYPE_STAR || 
		m_Type == PICKUP_ORB_RED ||
		m_Type == PICKUP_ORB_GREEN ||
		m_Type == PICKUP_ORB_BLUE ||
		m_Type == PICKUP_TYPE_1UP 
		)
	{
		m_State = PICKUP_STATE_SPAWN_MOVEMENT;
		m_SpawnMovementDegree = (float)num::RAND32::Instance().RandInt(0,359);
		m_SpawnMovementTime =   num::RAND32::Instance().RandFloat(0.5f,1.0f);
	}
	else
	{
		m_State = PICKUP_STATE_CIRCLE_AROUND;
	}
	
    m_IsAlive = true;
	m_CircleCounter.Reset();
	m_CircleCounter.Tick(num::RAND32::Instance().RandFloat(0.0f,0.9f));
	m_pSFX = FIGSFXManager::Instance().Spawn(FIGSfx::PICKUP_TRAIL,m_Pos , 1.0f);
}
	
void		FIGPickup::RenderShadow(const math::Vec2& Offset, float Scale)
{

}
	

void		FIGPickup::OnDie()
{

}

void		FIGPickup::HitTest()
{
	if(!FIGPlayerCraft::Instance().IsAlive())
		return;
	
	math::Vec2 Pos = FIGPlayerCraft::Instance().GetPos();
	float Radius = FIGPlayerCraft::Instance().GetRadius() * Fighter::Instance().GetScale();
	
	if(HitTest( Pos - math::Vec2(0,-Radius)))
		return;

	if(HitTest( Pos - math::Vec2(0, Radius)))
		return;

	if(HitTest( Pos - math::Vec2( -Radius,0)))
		return;

	if(HitTest( Pos - math::Vec2(Radius,0)))
		return;

	if(HitTest( Pos))
		return;
}

bool		FIGPickup::HitTest(const math::Vec2& P)
{
	float Scale = Fighter::Instance().GetScale();
	math::Vec2 TopLeft = m_Pos - (m_Sprite.m_SizeOriginal * 0.5f * Scale);
	math::Vec2 BottomRight =  m_Pos + (m_Sprite.m_SizeOriginal * 0.5f * Scale);

 	if(P.x < TopLeft.x)
		return false;
	if(P.x > BottomRight.x)
		return false;
	if(P.y < TopLeft.y)
		return false;
	if(P.y > BottomRight.y)
		return false;

	// HIT
	m_IsAlive = false;
		
	GotEaten();
	return true;

}

void		FIGPickup::GotEaten()
{
	switch(m_Type)
	{
		case PICKUP_TYPE_STAR:  		
			FIGSounds::Instance().PlaySoundSFX(FIGSounds::PICKUP_STAR);
		break;

		case PICKUP_TYPE_SHIELD:
			FIGSounds::Instance().PlaySoundSFX(FIGSounds::PICKUP_SHIELD);  		
		break;

		case PICKUP_TYPE_HEALTH:
		case PICKUP_TYPE_1UP:
			FIGSounds::Instance().PlaySoundSFX(FIGSounds::PICKUP_HEALTH);  		
		break;

		case PICKUP_ORB_BLUE:
		case PICKUP_ORB_GREEN:
		case PICKUP_ORB_RED:
			FIGSounds::Instance().PlaySoundSFX(FIGSounds::PICKUP_ORB);  					
			break;

		default:
			FIGSounds::Instance().PlaySoundSFX(FIGSounds::PICKUP_SFX);
		break;


	}
	
	if(m_Type < PICKUP_TYPE_WEAPON_COUNT)
	{
		if(m_Type == PICKUP_TYPE_WEAPON_BLUE)
		{
			FIGPlayerCraft::Instance().UpgradeWeapon(FIGPlayerCraft::WEAPON_BULE);
			FIGSFXManager::Instance().Spawn(FIGSfx::PICKUP_BULEWEAPON,m_Pos,2.0f);			
		}
		else if(m_Type == PICKUP_TYPE_WEAPON_RED)
		{
			FIGPlayerCraft::Instance().UpgradeWeapon(FIGPlayerCraft::WEAPON_RED);
			FIGSFXManager::Instance().Spawn(FIGSfx::PICKUP_REDWEAPON,m_Pos,2.0f);			
		}
		else if(m_Type == PICKUP_TYPE_WEAPON_GREEN)
		{
			FIGPlayerCraft::Instance().UpgradeWeapon(FIGPlayerCraft::WEAPON_GREEN);
			FIGSFXManager::Instance().Spawn(FIGSfx::PICKUP_GREENWEAPON,m_Pos,2.0f);			
		}
		
	}

	switch(m_Type)
	{	
		case PICKUP_TYPE_HEALTH:
			FIGPlayerCraft::Instance().RestoreHealth();
			FIGPickupAnimation::Instance().Animate(m_Pos, m_Type);
		break;

		case PICKUP_TYPE_NUKE:
			FIGPlayerCraft::Instance().IncreaseBombs();
			FIGPickupAnimation::Instance().Animate(m_Pos, m_Type);
		break;

		case PICKUP_TYPE_SHIELD:
			FIGConversation::Instance().PushTalk(FIGConversation::SPEECH_PLAYER_1,"LOC_LETROCK");
			FIGPlayerCraft::Instance().SuperArmor();
		break;

		case PICKUP_TYPE_ROKET_SHOOT:
			FIGPlayerCraft::Instance().PickupRocketShootToAllDir();
		break;

		case PICKUP_TYPE_STAR:
			FIGPlayerCraft::Instance().PickupStar();
			FIGSFXManager::Instance().Spawn(FIGSfx::PICKUP_STAR,m_Pos,2.0f);	
			FIGAwardTracker::Instance().GotStar();

			FIGPickupAnimation::Instance().Animate(m_Pos, m_Type);
			FIGPlayerCraft::Instance().IncreaseSpecialPowerCoolDown();
			
			{
				int C = FIGVars::Instance()->GetInt(FIGVars::VAR_NAMES_STARS_COLLECTED);
				if( C < FIGConstants::STARS_FOR_ACHIEVEMENT2)
				{
					C++;
					FIGVars::Instance()->SetInt(FIGVars::VAR_NAMES_STARS_COLLECTED,C);
					if(C >= FIGConstants::STARS_FOR_ACHIEVEMENT2)
					{
						FIGGameCenter::Instance().UpdateValue(FIGGameCenter::GOD_OF_ALIENS,true,true);
					}
				}
                else if(C < FIGConstants::STARS_FOR_ACHIEVEMENT1)
                {
                    C++;
					FIGVars::Instance()->SetInt(FIGVars::VAR_NAMES_STARS_COLLECTED,C);
					if(C >= FIGConstants::STARS_FOR_ACHIEVEMENT1)
					{
						FIGGameCenter::Instance().UpdateValue(FIGGameCenter::STARS_COLLECTOR,true,true);
					}
                }
			}
			// when there is cool down button
			m_State = PICKUP_EATEN_ANIMATION;

		break;

		case PICKUP_TYPE_1UP:
			FIGPlayerCraft::Instance().Pickup1Up();
			FIGPickupAnimation::Instance().Animate(m_Pos, m_Type);
		break;

		
		//case PICKUP_TYPE_GUARDIAN:
		//	FIGPlayerCraft::Instance().PickupGuardianAngel();
		//break;
	}
		
	if(m_pSFX)
	{
		m_pSFX->ToDie();
		m_pSFX = NULL;
	}

		

}

void		FIGPickup::Clear()
{
	if(m_pSFX)
	{
		m_pSFX->ToDie();
		m_pSFX = NULL;
	}
}


bool		FIGPickup::IsInSideScreen()
{
	return true;
}


std::string		FIGPickup::MapTypeToName(FIGPickup::PICKUP_TYPES Type)
{
	switch(Type)
	{
		case PICKUP_TYPE_HEALTH:
		return	"HEALTH";
	
		case PICKUP_TYPE_WEAPON_BLUE:
			return "WEAPON_BLUE";

		case PICKUP_TYPE_WEAPON_RED:
			return "WEAPON_RED"; 

		case PICKUP_TYPE_WEAPON_GREEN:
			return "WEAPON_GREEN";
	
		case PICKUP_TYPE_SHIELD:
			return "ARMOR";

		case PICKUP_TYPE_STAR:
			return "STAR";
	
		case PICKUP_TYPE_NUKE:
			return "NUKE";

		case PICKUP_TYPE_ROKET_SHOOT:
			return "ROKET_SHOOT";

		case PICKUP_TYPE_1UP:
			return "1UP";

		case PICKUP_ORB_RED:
			return "ORB_RED";

		case PICKUP_ORB_GREEN:
			return "ORB_GREEN";

		case PICKUP_ORB_BLUE:
			return "ORB_BLUE";	

		case PICKUP_NUKE_BUTTON:
			return "NUKE_BUTTON";

		default:
			break;
	}
    
	return "unknown";

}

FIGPickup::PICKUP_TYPES		FIGPickup::MapNameToType(const std::string& TypeName)
{
	for (unsigned int i = 0; i < PICKUP_COUNT; i++)
		if (strcmpi( MapTypeToName((PICKUP_TYPES)i).c_str(), TypeName.c_str() ) == 0)
			return (PICKUP_TYPES)i;

	return PICKUP_TYPE_NONE; 
	
}

